﻿//+-------------------------------------------------------------------------------------------------------------------------------------------------------
//
//Description: ViewDefParameterLocalizablePropertyViewModel
//Author: Aravind Ramarathinam (aravr@microsoft.com)
//
//Copyright © Microsoft Corporation
//Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 
//You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 
//
//THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, 
//INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. 
//See the Apache Version 2.0 License for specific language governing permissions and limitations under the License.
// 
//--------------------------------------------------------------------------------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.ComponentModel;
using VmroleAuthor.Models;

namespace VmroleAuthor.ViewModels
{
    public class ViewDefParameterLocalizablePropertyViewModel : ViewModelBase, IDataErrorInfo, ICleanupParamsAndPayload
    {
        private bool isLocalized;
        private string selectedPropertyValue;
        private readonly Func<string> optionalInitialValueGetter;

        private readonly Func<string> autoGeneratedPropertyParamName;  
        protected readonly ViewDefViewModel ViewDefViewModel;
        protected readonly Action<string> ModelValueSetter;
        protected readonly Func<string> ModelValueGetter;
        protected readonly string PropertyName;

        public static class PropertyNames
        {
            public const string IsLocalized = "IsLocalized";
            public const string PropertyValue = "PropertyValue";
            public const string SelectedPropertyValue = "SelectedPropertyValue";
        }
    

        public ViewDefParameterLocalizablePropertyViewModel(
           string propertyName,
           Func<string> modelValueGetter,
           Action<string> modelValueSetter,
           Func<string> autoGeneratedPropertyParamName,
           ViewDefViewModel viewDefViewModel,
           bool isRequired,
           Func<string> optionalInitialValueGetter)
        {
            this.PropertyName = propertyName;
            this.ModelValueGetter = modelValueGetter;
            this.ModelValueSetter = modelValueSetter;
            this.autoGeneratedPropertyParamName = autoGeneratedPropertyParamName;
            this.ViewDefViewModel = viewDefViewModel;
            this.IsRequired = isRequired;
            this.optionalInitialValueGetter = optionalInitialValueGetter;

            string localizableParamName;
            string newErr = ViewDefLocalizationHelper.ValidateAndGetLocalizableParameterName(modelValueGetter(), out localizableParamName);
            this.isLocalized = String.IsNullOrEmpty(newErr) && !string.IsNullOrEmpty(localizableParamName);
            if (this.isLocalized)
            {
                this.ViewDefViewModel.AddLocalizableParameterIfNotExist(localizableParamName, this.optionalInitialValueGetter);
            }
        }

        public List<string> AvailableLocalizedPropertyValues
        {
            get { return this.ViewDefViewModel.AvailableLocalizedPropertyValues; }
        }

        public bool IsRequired { get; set; }

        public bool IsLocalized
        {
            get { return this.isLocalized; }
            set
            {
                this.isLocalized = value;
                this.OnPropertyChanged(PropertyNames.PropertyValue);
                this.OnPropertyChanged(PropertyNames.IsLocalized);
            }
        }

        public string PropertyValue
        {
            get
            {
                return this.ModelValueGetter();
            }
            set
            {
                this.Set(value);               
                this.OnPropertyChanged(PropertyNames.PropertyValue);
                this.OnPropertyChanged(PropertyNames.IsLocalized);
            }
        }

        public string SelectedPropertyValue
        {
            get
            {
                return this.selectedPropertyValue;
            }
            set
            {
                if (value != null)
                {
                    this.Set(value);
                }
                this.selectedPropertyValue = this.PropertyValue;
                this.OnPropertyChanged(PropertyNames.SelectedPropertyValue);
                //Note: dont do this here -> this.OnPropertyChanged(PropertyName); 
            }
        }

        public bool AcceptsMultilineReturn
        {
            get
            {
                return true;
            }
        }

        public void Cleanup()
        {
            this.PropertyValue = null;
        }

        private void Set(string newValue)
        {
            if (newValue != null)
            {
                if (String.Equals(newValue, ViewDefViewModel.AutoLocalizeMoniker, StringComparison.Ordinal))
                {
                    string autoGenParamHint = autoGeneratedPropertyParamName();
                    if (String.IsNullOrEmpty(autoGenParamHint))
                    {
                        Random random = new Random();
                        autoGenParamHint = ViewDefViewModel.AutoGeneratedLocParamPrefix + random.Next();
                    }
                    newValue = ViewDefLocalizationHelper.GenerateLocalizableString(autoGenParamHint);
                }

                if (String.Equals(newValue, this.ModelValueGetter(), StringComparison.Ordinal))
                {
                    // already set, just ignore   
                    return;
                }
            }           
         
            string oldLocalizedParamName;
            string oldErr = ViewDefLocalizationHelper.ValidateAndGetLocalizableParameterName(this.ModelValueGetter(), out oldLocalizedParamName);

            this.ModelValueSetter(newValue);

            string localizableParamName;
            string newErr = ViewDefLocalizationHelper.ValidateAndGetLocalizableParameterName(this.ModelValueGetter(), out localizableParamName);
            this.isLocalized = false;
            if (String.IsNullOrEmpty(newErr) && !string.IsNullOrEmpty(localizableParamName))
            {
                // parameterized/ localized               
                this.ViewDefViewModel.AddLocalizableParameterIfNotExist(localizableParamName, this.optionalInitialValueGetter);                
                this.isLocalized = true;
            }


            if (String.IsNullOrEmpty(oldErr) && !string.Equals(localizableParamName, oldLocalizedParamName, StringComparison.Ordinal))
            {
                //Remove old
                this.ViewDefViewModel.RemoveLocalizableParameterIExists(oldLocalizedParamName);
            }          
        }

        public string this[string propName]
        {
            get
            {
                string error = null;
                switch (propName)
                {
                    case PropertyNames.PropertyValue:
                        if (this.IsLocalized)
                        {
                            error = ViewDefLocalizationHelper.ValidatePropertyLocalized(this.ModelValueGetter(), this.ViewDefViewModel);
                            if (!String.IsNullOrEmpty(error))
                            {
                                error = this.PropertyName + " " + error;
                            }
                        }
                        else
                        {
                            error = ViewDefLocalizationHelper.ValidatePropertyNotLocalized(this.ModelValueGetter(), this.IsRequired);
                            if (!String.IsNullOrEmpty(error))
                            {
                                error = this.PropertyName + " " + error;
                            }
                            else      
                            {
                                // DoTypeSpecificValidation(); 
                                if (this.IsRequired && this.ModelValueGetter() == null)
                                {
                                    return PropertyName + " Must be specified";
                                }
                            }     
                        }

                        break;
                }
                return error;
            }
        }

        public string Error { get; set; }       
    }
}
